home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / DJEMU106.ARJ / EMU.CC < prev    next >
C/C++ Source or Header  |  1992-04-07  |  10KB  |  370 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "emu.h"
  4. #include "const.h"
  5.  
  6. int modrm;
  7.  
  8. #if 0
  9. char saw[256*8];
  10.  
  11. /* zero here means invalid.  If first entry starts with '*', use st(i) */
  12. /* no assumed %EFs here.  Indexed by rm(modrm()) */
  13. char *f0[] = {0, 0, 0, 0, 0, 0, 0, 0};
  14. char *fop_9[]  = { "*fxch st,%GF" };
  15. char *fop_10[] = { "fnop", 0, 0, 0, 0, 0, 0, 0 };
  16. char *fop_12[] = { "fchs", "fabs", 0, 0, "ftst", "fxam", 0, 0 };
  17. char *fop_13[] = { "fld1", "fldl2t", "fldl2e", "fldpi",
  18.                    "fldlg2", "fldln2", "fldz", 0 };
  19. char *fop_14[] = { "f2xm1", "fyl2x", "fptan", "fpatan",
  20.                    "fxtract", "fprem1", "fdecstp", "fincstp" };
  21. char *fop_15[] = { "fprem", "fyl2xp1", "fsqrt", "fsincos",
  22.                    "frndint", "fscale", "fsin", "fcos" };
  23. char *fop_21[] = { 0, "fucompp", 0, 0, 0, 0, 0, 0 };
  24. char *fop_28[] = { 0, 0, "fclex", "finit", 0, 0, 0, 0 };
  25. char *fop_32[] = { "*fadd %GF,st" };
  26. char *fop_33[] = { "*fmul %GF,st" };
  27. char *fop_36[] = { "*fsubr %GF,st" };
  28. char *fop_37[] = { "*fsub %GF,st" };
  29. char *fop_38[] = { "*fdivr %GF,st" };
  30. char *fop_39[] = { "*fdiv %GF,st" };
  31. char *fop_40[] = { "*ffree %GF" };
  32. char *fop_42[] = { "*fst %GF" };
  33. char *fop_43[] = { "*fstp %GF" };
  34. char *fop_44[] = { "*fucom %GF" };
  35. char *fop_45[] = { "*fucomp %GF" };
  36. char *fop_48[] = { "*faddp %GF,st" };
  37. char *fop_49[] = { "*fmulp %GF,st" };
  38. char *fop_51[] = { 0, "fcompp", 0, 0, 0, 0, 0, 0 };
  39. char *fop_52[] = { "*fsubrp %GF,st" };
  40. char *fop_53[] = { "*fsubp %GF,st" };
  41. char *fop_54[] = { "*fdivrp %GF,st" };
  42. char *fop_55[] = { "*fdivp %GF,st" };
  43. char *fop_60[] = { "fstsw ax", 0, 0, 0, 0, 0, 0, 0 };
  44.  
  45. char **fspecial[] = { /* 0=use st(i), 1=undefined 0 in fop_* means undefined */
  46.   0, 0, 0, 0, 0, 0, 0, 0,
  47.   0, fop_9, fop_10, 0, fop_12, fop_13, fop_14, fop_15,
  48.   f0, f0, f0, f0, f0, fop_21, f0, f0,
  49.   f0, f0, f0, f0, fop_28, f0, f0, f0,
  50.   fop_32, fop_33, f0, f0, fop_36, fop_37, fop_38, fop_39,
  51.   fop_40, f0, fop_42, fop_43, fop_44, fop_45, f0, f0,
  52.   fop_48, fop_49, f0, fop_51, fop_52, fop_53, fop_54, fop_55,
  53.   f0, f0, f0, f0, fop_60, f0, f0, f0,
  54.   };
  55.  
  56. char *floatops[] = { /* assumed " %EF" at end of each.  mod != 3 only */
  57. /*00*/ "fadd", "fmul", "fcom", "fcomp",
  58.        "fsub", "fsubr", "fdiv", "fdivr",
  59. /*08*/ "fld", 0, "fst", "fstp",
  60.        "fldenv", "fldcw", "fstenv", "fstcw",
  61. /*16*/ "fiadd", "fimul", "ficomw", "ficompw",
  62.        "fisub", "fisubr", "fidiv", "fidivr",
  63. /*24*/ "fild", 0, "fist", "fistp",
  64.        "frstor", "fldt", 0, "fstpt",
  65. /*32*/ "faddq", "fmulq", "fcomq", "fcompq",
  66.        "fsubq", "fsubrq", "fdivq", "fdivrq",
  67. /*40*/ "fldq", 0, "fstq", "fstpq",
  68.        0, 0, "fsave", "fstsww",
  69. /*48*/ "fiaddw", "fimulw", "ficomw", "ficompw",
  70.        "fisubw", "fisubrw", "fidivw", "fidivr",
  71. /*56*/ "fildw", 0, "fistw", "fistpw",
  72.        "fbldt", "fildq", "fbstpt", "fistpq"
  73.   };
  74. #endif
  75.  
  76. int status_word = 0;
  77. int control_word = 0x77e;
  78. reg regs[8] = {
  79.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  80.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  81.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  82.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  83.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  84.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  85.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  86.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  87. };
  88. int top = 0;
  89.  
  90. FUNC esc_table[64] = {
  91.   emu_00, emu_10, emu_20, emu_30, emu_40, emu_50, emu_60, emu_70,
  92.   emu_01, emu_11, emu_21, emu_31, emu_41, emu_51, emu_61, emu_71,
  93.   emu_02, emu_12, emu_22, emu_32, emu_42, emu_52, emu_62, emu_72,
  94.   emu_03, emu_13, emu_23, emu_33, emu_43, emu_53, emu_63, emu_73,
  95.   emu_04, emu_14, emu_24, emu_34, emu_44, emu_54, emu_64, emu_74,
  96.   emu_05, emu_15, emu_25, emu_35, emu_45, emu_55, emu_65, emu_75,
  97.   emu_06, emu_16, emu_26, emu_36, emu_46, emu_56, emu_66, emu_76,
  98.   emu_07, emu_17, emu_27, emu_37, emu_47, emu_57, emu_67, emu_77,
  99. };
  100.  
  101. int emu_initted = 0;
  102.  
  103. void emu_entry()
  104. {
  105.   if (emu_initted != 0x12345678)
  106.   {
  107.     emu_initted = 0x12345678;
  108. //    eprintf(
  109. //    "Installing the 80387 Emulator.  Copyright (C) 1991 DJ Delorie.\n"
  110. //    "WARNING: This is a TEST version of this emulator.  If it doesn't work,\n"
  111. //    "then don't use it.  Not all of the opcodes are implemented, and the\n"
  112. //    "ones that are may not work right in extreme cases.  Use at your own risk.\n"
  113. //    );
  114.   }
  115. //  eprintf("eax=0x%08x ebx=0x%08x ecx=0x%08x edx=0x%08x\n", eax, ebx, ecx, edx);
  116. //  eprintf("esi=0x%08x edi=0x%08x ebp=0x%08x eip=0x%08x\n", esi, edi, ebp, eip);
  117.   if (*eip == 0x66) // operand size - we know what size we need
  118.     eip++;
  119.   if (*eip == 0x9b) // fwait
  120.     return;
  121. #if 0
  122.   int see = ((int)(eip[0] & 7) << 8) | eip[1];
  123.   if (saw[see] != 42)
  124.   {
  125.     eprintf("EMU387: %02x %02x %02x %02x - e%d%d", eip[0], eip[1], eip[2], eip[3], eip[0]&7, (eip[1]>>3)&7);
  126.     eprintf(" s%d  ", eip[1]&7);
  127.     int esc = ((eip[0]<<3)&070) | ((eip[1]>>3)&007);
  128.     int modrm = eip[1];
  129.     if ((modrm>>6) == 3)
  130.       if (fspecial[esc])
  131.         if (fspecial[esc][0] && (fspecial[esc][0][0] == '*'))
  132.             eprintf("%s\n", fspecial[esc][0]+1);
  133.         else if (fspecial[esc][modrm&7])
  134.             eprintf("%s\n", fspecial[esc][modrm&7]);
  135.         else
  136.           eprintf("<invalid>\n");
  137.       else
  138.         eprintf("%s st(i)\n", floatops[esc]);
  139.     else
  140.       eprintf("%s st(i)\n", floatops[esc]);
  141.     saw[see] = 42;
  142.   }
  143. #endif
  144.   int esc_value = *eip++ & 7;
  145.   modrm = *eip++;
  146.   esc_value |= (modrm & 070);
  147.   (esc_table[esc_value])();
  148. //  emu_printall();
  149. }
  150.  
  151. void emu_bad()
  152. {
  153.   eprintf("Unimplemented 80387 Opcode at eip=0x%08x : %02x", eip-2, eip[-2]);
  154.   if (eip[-1] > 0277)
  155.     eprintf(" %02x", eip[-1]);
  156.   else
  157.     eprintf(" /%d", (eip[-1]>>3)&7);
  158.   eprintf(" - e%d%d", eip[-2]&7, (eip[-1]>>3)&7);
  159.   if (eip[-1] > 0277)
  160.     eprintf(" s%d", eip[-1]&7);
  161.   eprintf("\n");
  162.   exception(EX_I);
  163. }
  164.  
  165. void emu_printall()
  166. {
  167.   static char *tag_desc[] = { "Valid", "Zero", "Special", "Empty" };
  168.   status_word = status_word & ~SW_TOP;
  169.   status_word += (top&7) * SW_TOPS;
  170.   eprintf("  SW: 0x%04x  top=%d cc=%d%d%d%d    ", status_word, top&7,
  171.     status_word & SW_C3?1:0, status_word & SW_C2?1:0,
  172.     status_word & SW_C1?1:0, status_word & SW_C0?1:0);
  173.   eprintf("CW: 0x%04x\n", control_word);
  174.   for (int i=0; i<8; i++)
  175.   {
  176.     reg *r = &st(i);
  177.     switch (r->tag)
  178.     {
  179.       case TW_E:
  180.         continue;
  181.         eprintf("st(%d)                                ", i);
  182.         break;
  183.       case TW_Z:
  184.         eprintf("st(%d) %c .0000 0000 0000 0000         ",
  185.                 i, r->sign ? '-' : '+');
  186.         break;
  187.       case TW_S:
  188.       case TW_V:
  189.         eprintf("st(%d) %c .%04x %04x %04x %04x e%+-6d ", i,
  190.           r->sign ? '-' : '+',
  191.           (long)(r->sigh >> 16),
  192.           (long)(r->sigh & 0xFFFF),
  193.           (long)(r->sigl >> 16),
  194.           (long)(r->sigl & 0xFFFF),
  195.           r->exp - EXP_BIAS + 1);
  196.     }
  197.     eprintf("%s\n", tag_desc[r->tag]);
  198.   }
  199.   fflush(stderr);
  200. }
  201.  
  202. static struct {
  203.   int type;
  204.   char *name;
  205. } ex_names[] = {
  206.   EX_SO, "stack overflow",
  207.   EX_SU, "stack underflow",
  208.   EX_P, "loss of precision",
  209.   EX_U, "underflow",
  210.   EX_O, "overflow",
  211.   EX_Z, "divide by zero",
  212.   EX_D, "denormalized operand",
  213.   EX_I, "invalid operation",
  214.   0,0
  215. };
  216.  
  217. void exception(int n)
  218. {
  219.   int i;
  220.   status_word |= n;
  221.   if (n == EX_SU)
  222.     status_word &= ~SW_C1;
  223.   for (i=0; ex_names[i].type; i++)
  224.     if (ex_names[i].type == n)
  225.       break;
  226.   if (ex_names[i].type)
  227.     eprintf("80387 Exception: %s!\n", ex_names[i].name);
  228.   else
  229.     eprintf("80387 Exception: 0x%04x!\n", n);
  230.   if (~control_word & n & CW_EXM)
  231.   {
  232.     emu_printall();
  233.     asm("movl $0x4cff,%eax");
  234.     asm("int $0x21");
  235.   }
  236. }
  237.  
  238. void setcc(int cc)
  239. {
  240.   status_word &= ~(SW_C0|SW_C1|SW_C2|SW_C3);
  241.   status_word |= cc & (SW_C0|SW_C1|SW_C2|SW_C3);
  242. }
  243.  
  244. int full()
  245. {
  246.   if (st(7).tag != TW_E)
  247.   {
  248.     exception(EX_SO);
  249.     top--;
  250.     r_mov(CONST_NAN, st(0));
  251.     return 1;
  252.   }
  253.   return 0;
  254. }
  255.  
  256. int empty(int i)
  257. {
  258.   if (st(i).tag == TW_E)
  259.   {
  260.     exception(EX_SU);
  261.     return 1;
  262.   }
  263.   return 0;
  264. }
  265.  
  266. static int sregval(int reg, int mod)
  267. {
  268.   switch (reg)
  269.   {
  270.     case 0: return eax;
  271.     case 1: return ecx;
  272.     case 2: return edx;
  273.     case 3: return ebx;
  274.     case 4: return (mod==-1) ? 0 : esp;
  275.     case 5: return mod ? ebp : 0; // data
  276.     case 6: return esi;
  277.     case 7: return edi;
  278.   }
  279. }
  280.  
  281. static int scale[] = { 1, 2, 4, 8 };
  282.  
  283. static int getsib()
  284. {
  285.   int mod = modrm >> 6;
  286.   int sib = *eip++;
  287.   int ss = sib>>6;
  288.   int index = (sib>>3) & 7;
  289.   int base = sib & 7;
  290.   int rv = sregval(base, mod) + sregval(index, -1) * scale[ss];
  291.   int rv2;
  292.   switch (mod)
  293.   {
  294.     case 1:
  295.       rv2 = *(signed char *)eip++;
  296.       rv += rv2;
  297.       break;
  298.     case 0:
  299.       if (base != 5)
  300.         break;
  301.     case 2:
  302.       ((unsigned char *)&rv2)[0] = *eip++;
  303.       ((unsigned char *)&rv2)[1] = *eip++;
  304.       ((unsigned char *)&rv2)[2] = *eip++;
  305.       ((unsigned char *)&rv2)[3] = *eip++;
  306.       rv += rv2;
  307.       break;
  308.   }
  309.   return rv;
  310. }
  311.  
  312. static int regval(int reg, int mod)
  313. {
  314.   switch (reg)
  315.   {
  316.     case 0: return eax;
  317.     case 1: return ecx;
  318.     case 2: return edx;
  319.     case 3: return ebx;
  320.     case 4: return getsib();
  321.     case 5: return mod ? ebp : 0; // data
  322.     case 6: return esi;
  323.     case 7: return edi;
  324.   }
  325. }
  326.  
  327. void *get_modrm()
  328. {
  329.   int mod = modrm>>6;
  330.   int rm = modrm & 7;
  331.   int rv;
  332.   switch (mod)
  333.   {
  334.     case 0:
  335.       if (rm == 5)
  336.       {
  337.         ((unsigned char *)&rv)[0] = *eip++;
  338.         ((unsigned char *)&rv)[1] = *eip++;
  339.         ((unsigned char *)&rv)[2] = *eip++;
  340.         ((unsigned char *)&rv)[3] = *eip++;
  341.       }
  342.       else
  343.         rv = regval(rm, mod);
  344.       break;
  345.     case 1:
  346.       if (rm != 4)
  347.         rv = (*(signed char *)eip++) + regval(rm, mod);
  348.       else
  349.         rv = regval(rm, mod);
  350.       break;
  351.     case 2:
  352.       if (rm != 4)
  353.       {
  354.         ((unsigned char *)&rv)[0] = *eip++;
  355.         ((unsigned char *)&rv)[1] = *eip++;
  356.         ((unsigned char *)&rv)[2] = *eip++;
  357.         ((unsigned char *)&rv)[3] = *eip++;
  358.         rv += regval(rm, mod);
  359.       }
  360.       else
  361.         rv = regval(rm, mod);
  362.       break;
  363.     case 3:
  364.       eprintf("Attempt to get address from mod = 3\n");
  365.       exit(1);
  366.   }
  367. //  eprintf("modrm returning 0x%x\n", rv);
  368.   return (void *)rv;
  369. }
  370.